package net.koodar.forge.system.user.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import net.koodar.forge.common.utils.BeanUtil;
import net.koodar.forge.mybatis.util.PageUtil;
import net.koodar.forge.system.menu.manager.MenuManager;
import net.koodar.forge.system.menu.service.assembler.MenuAssembler;
import net.koodar.forge.system.role.manager.RoleManager;
import net.koodar.forge.system.role.manager.UserRoleManager;
import net.koodar.forge.system.user.model.dto.AdjDepartmentParamDTO;
import net.koodar.forge.system.user.model.dto.UserParamDTO;
import net.koodar.forge.system.user.model.dto.UserQueryDTO;
import net.koodar.forge.system.user.model.vo.UserVO;
import net.koodar.forge.system.menu.model.entity.Menu;
import net.koodar.forge.system.role.model.entity.Role;
import net.koodar.forge.system.user.model.entity.User;
import net.koodar.forge.system.role.model.entity.UserRole;
import net.koodar.forge.system.user.manager.UserManager;
import net.koodar.forge.common.code.UserErrorCode;
import net.koodar.forge.common.domain.dto.Response;
import net.koodar.forge.common.domain.dto.SingleResponse;
import net.koodar.forge.common.domain.model.AppUserDetails;
import net.koodar.forge.system.user.service.assembler.UserAssembler;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 用户业务app层
 *
 * @author liyc
 */
@Service
@RequiredArgsConstructor
public class UserService {

	private final UserRoleManager userRoleManager;
	private final RoleManager roleManager;
	private final PasswordEncoder passwordEncoder;
	private final UserManager userManager;
	private final MenuManager menuManager;
	private final UserAssembler userAssembler;
	private final MenuAssembler menuAssembler;


	/**
	 * 根据用户名判断用户是存在
	 * @param username
	 * @return
	 */
	public Boolean isExistsByUsername(String username) {
		return userManager.checkExistsUsername(username);
	}

	/**
	 * 创建初始管理员账号
	 */
	@Transactional(rollbackFor = Exception.class)
	public void createAdministrator(String username, String password, String roleName) {
		User user = new User();
		user.setUsername(username);
		user.setNickname(username);
		user.setDescription("超级管理员用户");
		user.setPassword(passwordEncoder.encode(password));
		user.setAdministratorFlag(true);
		userManager.save(user);

		Role role = new Role();
		role.setName(roleName);
		role.setCode(roleName);
		role.setDescription("超级管理员");
		roleManager.save(role);

		userRoleManager.save(user.getId(), role.getId());
	}

	/**
	 * 获取当前用户信息
	 */
	public Response getUserInfo() {
		AppUserDetails userDetails = (AppUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

		User user = userManager.findById(userDetails.getUserId());
		UserVO userVo = userAssembler.convertToUserVO(user);

		List<Menu> menus = userDetails.getAdministratorFlag() ?
				menuManager.list() : menuManager.listPermissionByRoleIds(userDetails.getRoleIds());
		userVo.setPermissions(menuAssembler.convertToPairPermissions(menus));
		return SingleResponse.ok(userVo);
	}

	/**
	 * 根据用户ID获取用户信息
	 * @param userId 用户ID
	 */
	public Response getUserInfo(long userId) {
		User user = userManager.findById(userId);
		UserVO userVo = BeanUtil.copy(user, UserVO.class);
		return SingleResponse.ok(userVo);
	}

	/**
	 * 更新当前用户密码
	 * @param oldPassword 旧密码
	 * @param newPassword 新密码
	 */
	public Response updatePassword( String oldPassword, String newPassword) {
		AppUserDetails userDetails = (AppUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

		User user = userManager.findById(userDetails.getUserId());
		if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
			return Response.error(UserErrorCode.PARAM_ERROR, "原密码错误，请重新输入。");
		}
		user.setPassword(passwordEncoder.encode(newPassword));
		userManager.save(user);
		return Response.ok();
	}

	/**
	 * 获取用户列表
	 * @param userQuery 用户查询条件
	 */
	public Response pageBy(UserQueryDTO userQuery) {
		Page<User> userPage = userManager.page(userQuery.toPage(), userQuery.toQueryWrapper());
		List<UserVO> records = userPage.getRecords().stream().map(userAssembler::convertToUserVO).toList();
		return SingleResponse.ok(PageUtil.toPage(records, userPage.getTotal()));
	}

	/**
	 * 添加用户
	 * @param userParamDTO 用户信息
	 */
	public Response addUser(UserParamDTO userParamDTO) {
		// 验证用户是否存在
		boolean existsFlag = userManager.checkExistsUsername(userParamDTO.getUsername());
		if (existsFlag) {
			return Response.error(UserErrorCode.PARAM_ERROR, "抱歉，该用户名已经被注册过了");
		}

		User user = userAssembler.convertToUser(userParamDTO);

		String randomPassword = RandomStringUtils.randomAlphanumeric(8);
		user.setPassword(passwordEncoder.encode(randomPassword));

		// 保存用户信息
		userManager.save(user);
		// 保存用户角色信息
		userRoleManager.saveBatch(userParamDTO.toUserRoles());
		return Response.ok();
	}

	/**
	 * 更新用户信息
	 * @param userParamDTO 用户信息
	 */
	public Response updateUser(UserParamDTO userParamDTO) {
		User user = userManager.findById(userParamDTO.getUserId());
		userAssembler.convertToUser(user, userParamDTO);
		// 保存用户信息
		userManager.save(user);
		// 保存用户角色信息
		List<UserRole> userRoles = userRoleManager.findAllByUserId(userParamDTO.getUserId());
		userRoleManager.removeBatchByIds(userRoles);
		userRoleManager.saveBatch(userParamDTO.toUserRoles());
		return Response.ok();
	}

	/**
	 * 批量删除用户
	 * @param userId 用户ID集合
	 */
	public Response batchUpdateDeleteFlag(List<Long> userId) {
		List<User> userList = userManager.listByIds(userId);
		if (userList.isEmpty()) {
			return Response.ok();
		}
		for (User user : userList) {
			if (user.getAdministratorFlag()) {
				return Response.error(UserErrorCode.PARAM_ERROR, "超级管理员用户不能删除哦~");
			}
		}
		userManager.removeBatchByIds(userList);
		return Response.ok();
	}

	/**
	 * 禁用用户
	 * @param userId 用户ID
	 */
	public Response disabledUser(long userId) {
		User user = userManager.findById(userId);
		if (user.getAdministratorFlag()) {
			return Response.error(UserErrorCode.PARAM_ERROR, "您不能禁用超级管理员哦~");
		}
		userManager.disabledUser(user);
		return Response.ok();
	}

	/**
	 * 更新用户部门
	 */
	public Response adjustDepartment(AdjDepartmentParamDTO adjDepartmentParamDTO) {
		List<Long> userIds = adjDepartmentParamDTO.getUserIds();
		for (Long userId : userIds) {
			User user = userManager.findById(userId);
			user.setDepartmentId(adjDepartmentParamDTO.getDepartmentId());
			userManager.saveOrUpdate(user);
		}
		return Response.ok();
	}

	/**
	 * 重置密码
	 * @param userId 用户ID
	 */
	public Response resetPassword(long userId) {
		String randomPassword = randomPassword();
		User user = userManager.findById(userId);
		user.setPassword(passwordEncoder.encode(randomPassword));
		userManager.save(user);
		return SingleResponse.ok(randomPassword);
	}

	/**
	 * 生成随机密码
	 */
	private String randomPassword() {
		return RandomStringUtils.randomNumeric(6) + RandomStringUtils.randomAlphabetic(2).toLowerCase();
	}
}
